﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

namespace Utils
{
    public class UITool : MonoBehaviour
    {
        
        #region 克隆&实例化对象(预制体)

        public static GameObject InstantiatePrefab(string path, string name)
        {
            GameObject o = Instantiate(LoadPrefab(path));
            o.name = name;
            return o;
        }
        
        public static GameObject InstantiatePrefabWithParent(GameObject parent, string path, string name)
        {
           GameObject o = Instantiate(LoadPrefab(path), parent.transform);
           o.name = name;
           return o;
        }
        
        public static GameObject InstantiatePrefabUI(string path, string name)
        {
            GameObject o = Instantiate(LoadPrefab(path), GameController.Instance().gameUIRoot);
            o.name = name;
            return o;
        }
        
        #endregion
        
        #region 加载预制体(用于减少手写配置路径的string长度）
        
        public static GameObject LoadPrefab(string rootPath)
        {
#if UNITY_EDITOR
            print("Loading : " + rootPath);
#endif
            return (GameObject)Resources.Load("Prefabs/" + rootPath);
        }
        
        #endregion
        
        #region 根据路径获取节点上的 <T> 组件

        public static T GetComponent<T>(string cascadePath, GameObject fromRoot) where T : Component
        {
            string[] names = cascadePath.Split('/');
            GameObject lastObject = fromRoot;

            foreach (string node in names)
            {
                lastObject = GetChildGameObject(node, lastObject);
                if (lastObject == null)
                    break;
            }

            if (lastObject == null)
            {
                Debug.LogError($"Cascade Name  \"{cascadePath}\"  is  an  invalid node path.");
                return null;
            }

            T widget = lastObject.GetComponent<T>();
            if (widget == null)
            {
                Debug.LogError($"Component {typeof(T).Name} doesn't  found in GameObject  \"{lastObject.name}\"");
                return null;
            }

            return widget;
        }

        #endregion

        #region 根据路径搜索节点并获取

        public static GameObject GetGameObjectByPath(string cascadePath, GameObject root)
        {
            GameObject lastObject = root;
            if (!string.IsNullOrEmpty(cascadePath))
            {
                string[] names = cascadePath.Split('/');
                foreach (var node in names)
                {
                    lastObject = GetChildGameObject(node, lastObject);
                    if (!lastObject)
                    {
                        break;
                    }
                }

                if (!lastObject)
                {
                    Debug.LogError($"Cascade Path  \"{cascadePath}\"  is  an  invalid node path.");
                    return null;
                }
            }

            return lastObject;
        }

        #endregion

        #region 获取所有子节点(返回List<>)

        public static List<GameObject> GetAllChildGameObject(GameObject widget)
        {
            List<GameObject> list = new List<GameObject>();
            foreach (Transform child in widget.transform)
            {
                list.Add(child.gameObject);
            }

            return list;
        }

        #endregion
        
        #region 获取子节点

        public static GameObject GetChildGameObject(string name, GameObject widget)
        {
            foreach (Transform child in widget.transform)
            {
                if (child.name.Equals(name))
                {
                    return child.gameObject;
                }
            }

            return null;
        }

        #endregion

        #region 注册触发事件

        /// <summary>
        /// 为对象添加监听事件
        /// </summary>
        /// <param name="obj">注册事件的对象</param>
        /// <param name="eventType">添加的事件类型</param>
        /// <param name="callback">事件的触发回调</param>
        public static void AddEventTriggerEvent(GameObject obj, EventTriggerType eventType,
            UnityAction<BaseEventData> callback)
        {
            EventTrigger.Entry entry = null;
            EventTrigger trigger;
            if ((trigger = obj.GetComponent<EventTrigger>()) == null)   //已有EventTrigger,获取
                trigger = obj.AddComponent<EventTrigger>(); //没有EventTrigger,添加

            // 查找事件 是否已注册
            foreach (EventTrigger.Entry existingEntry in trigger.triggers)
            {
                if (existingEntry.eventID == eventType)
                {
                    entry = existingEntry;
                    break;
                }
            }
            
            // 确认事件 未注册,进行注册
            if (entry==null)
            {
                entry = new EventTrigger.Entry();
                entry.eventID = eventType;
                // 覆盖原回调
                entry.callback = new EventTrigger.TriggerEvent();
            }
            
            entry.callback.AddListener(callback);
            trigger.triggers.Add(entry);

        }

        #endregion
    }
}